SSM ドキュメントでのコマンド実行制限を考えてみた

SSM ドキュメントでのコマンド実行制限を考えてみた

Clock Icon2024.07.17

こんにちは、森田です。

SSM ドキュメントでのコマンド実行制限を考える機会があったため、そのまとめ記事となります。

前提

ユーザーが SSM ドキュメントを利用して、コマンドを実行するケースを想定しています。
また、ドキュメントタイプは、セッションドキュメントとします。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-restrict-command-access.html

コマンド単体での制限

SSM ドキュメントでは、 allowedPattern を使って正規表現でコマンド単位での実行制限をかけることができます。

例えば、以下のドキュメントでは、lsとtail のみの実行が可能となります。

lsとtailのみ実行可能
schemaVersion: '1.0'
description: Run only ls and tail
sessionType: InteractiveCommands
parameters:
  command:
    type: String
    description: Allowed command
    allowedPattern: ^(ls|tail)$
properties:
  linux:
    commands: "{{ command }}"
    runAsElevated: true

以下のようなコマンドは実行できるようになります。

OK例
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls"

一方で、このドキュメントでは、コマンド単体での実行のみ可能なためオプションの指定ができません。

NG例
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls -l"

コマンド単体、オプションでの制限

今度は、オプションについてもドキュメント内に記載して制限を行います。
parametersにoptionを追加して、許可するオプションを記述します。

オプションありでlsとtailのみ実行可能
schemaVersion: '1.0'
description: Run ls and tail with options
sessionType: InteractiveCommands
parameters:
  command:
    type: String
    description: Allowed command
    allowedPattern: ^(ls|tail)$
  option:
    type: String
    description: Allowed option
    allowedPattern: ^(-l|-a)$

properties:
  linux:
    commands: "{{ command }} {{option}}"
    runAsElevated: true
OK例
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls",option="-l" 
NG例
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls",option="-s" 

このドキュメントでは、許可されたオプションは実行できますが、オプションをすべて定義することは現実的ではないですね。
また、 ls -l | grep zip のようなパイプ処理をしたい場合にもこの記述では対応できません。

コマンド単体、パイプでの制限

今度は、コマンド単体で制限を行いながら、パイプ処理が行えるようなケースを考えてみます。
また、パイプ処理についても実行できるコマンドに制限をかけたいです。

このケースを実現させるには、parametersのallowedPatternだけでは難しく、properties内のcommands側で制御すればできます。
ただし、commands側で制御するため、 SSM ドキュメント自体は実行できる状態となります。

例えば、以下の記述であれば、aliasを使用して、mysqlコマンドを事前に無効化することができます。

aliasを利用したmysql禁止
schemaVersion: '1.0'
description: Restrictions on commands and pipes (mysql prohibited)
sessionType: InteractiveCommands
parameters:
  command:
    type: String
    description: Allowed command
    allowedPattern: ^(ls|tail)$
  option:
    type: String
    description: option
properties:
  linux:
    commands: |
      alias mysql="echo 'mysql command is disabled'"
      {{command}} {{option}}
    runAsElevated: true

このドキュメントを使って以下のコマンドを実行してみます。

実行例
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls",option="-l| mysql --version" 

すると、以下のように実行自体はできるものの、mysqlが無効化されていることが表示されます。

実行結果
mysql command is disabled --version

Exiting session with sessionId: xxx-wezw6qkmkctzhjbpl2lkldzi6m.

ただし、このケースでも直接 /usr/bin/mysql を実行されるケースには対応できません。

mysql自体のコマンド入力を禁止するために、以下のようにsedを使ってmysqlの文字をリプレイスすることで上記のようなケースに無理やり対応させることはできます。

コマンド実行前のreplace処理
schemaVersion: '1.0'
description: Restrictions on commands and pipes (mysql prohibited)
sessionType: InteractiveCommands
parameters:
  command:
    type: String
    description: Allowed command
    allowedPattern: ^(ls|tail)$
  option:
    type: String
    description: Allowed option
properties:
  linux:
    commands: |
      cleaned_command=$(echo "{{command}} {{option}}" | sed 's/mysql//g')
      echo "実行されるコマンド: $cleaned_command"
      eval "$cleaned_command"

    runAsElevated: true
実行結果
実行されるコマンド: ls -l| /usr/bin/ --version
sh: line 3: /usr/bin/: Is a directory

ただ、このような方法では、コマンドの作り込みが必要となるため、コマンド制限が厳しい場合は、上記のようなドキュメントもマッチしない可能性があります。

まとめ

SSM ドキュメント内のパラメータを使ったコマンド実行制限については、正規表現で行うため、表現できる制限には限界があります。

また、properties内のcommands側である程度はどうにかできますが、厳しい制限をかけたい場合はマッチしないかと思います。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.